home *** CD-ROM | disk | FTP | other *** search
/ Ultimedia 2 / Ultimedia 2.iso / tools / animplayer / amipeg / source.lha / video.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-03  |  54.3 KB  |  2,076 lines

  1. /*
  2.  *  This file contains C code that implements the video decoder model.
  3.  */
  4.  
  5. #include "video.h"
  6. #include "proto.h"
  7. #include "decoders.h"
  8. #include "util.h"
  9.  
  10. #include <time.h>
  11.  
  12. #define static
  13.  
  14. /* Declarations of functions. */
  15. //static void init_stat_struct(Statval *);
  16. //static void PrintOneStat(void);
  17. //static void CollectStats(void);
  18. //static unsigned int bitCountRead(void);
  19. //static void StartTime(void);
  20. //static void EndTime(void);
  21. static int ParseSeqHead(VidStream *);
  22. static int ParseGOP(VidStream *);
  23. static int ParsePicture(VidStream *, TimeStamp);
  24. static int ParseSlice(VidStream *);
  25. static int ParseMacroBlock(VidStream *);
  26. static void ReconIMBlock(VidStream *, int);
  27. static void ReconPMBlock(VidStream *, int, int, int, int);
  28. static void ReconBMBlock(VidStream *, int, int, int, int);
  29. static void ReconBiMBlock(VidStream *, int, int, int, int, int, int);
  30. static void ProcessSkippedPFrameMBlocks(VidStream *);
  31. static void ProcessSkippedBFrameMBlocks(VidStream *);
  32. static void ReconSkippedBlock16(unsigned char *, unsigned char *, int, int, int, int, int, int, int);
  33. static void ReconSkippedBlock8(unsigned char *, unsigned char *, int, int, int, int, int, int, int);
  34. static void DoPictureDisplay(VidStream *);
  35.  
  36. extern int ditherType;
  37.  
  38. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  39. //#define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  40.  
  41. /* Declare global pointer to vid stream used for current decoding. */
  42.  
  43. VidStream *curVidStream = NULL;
  44.  
  45. /* Array mapping zigzag to array pointer offset. */
  46. int zigzag_direct[64] = {
  47.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  48.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  49.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  50.   58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  51.  
  52. /* Initialize P and B skip flags. */
  53.  
  54. static int No_P_Flag = 0;
  55. static int No_B_Flag = 0;
  56.  
  57. /* Max lum, chrom indices for illegal block checking. */
  58.  
  59. static int lmaxx, lmaxy, cmaxx, cmaxy;
  60.  
  61.  
  62. /*
  63.   The following accounts for time and size  spent in various parsing acitivites
  64.   if ANALYSIS has been defined.
  65. */
  66. #ifdef ANALYSIS
  67. #include "analysis.h"
  68. #endif
  69.  
  70. double realTimeStart;
  71. int totNumFrames = 0;
  72.  
  73. double ReadSysClock(void)
  74. {
  75.     unsigned int clock[2];
  76.  
  77.     (void) timer(clock);
  78.     return clock[0] + clock[1] / 1000000.0;
  79. }
  80.  
  81. void PrintTimeInfo(void)
  82. {
  83.     double spent = ReadSysClock() - realTimeStart;
  84.  
  85.     if (!quietFlag) {
  86.         printf("\nReal Time Spent (After Initializations): %f secs.\n", spent);
  87.         printf("Avg. Frames/Sec: %f\n", ((double) totNumFrames) / spent);
  88.     }
  89. }
  90.  
  91.  
  92.  
  93. /*
  94.  *--------------------------------------------------------------
  95.  *
  96.  * NewVidStream --
  97.  *
  98.  *    Allocates and initializes a VidStream structure. Takes
  99.  *      as parameter requested size for buffer length.
  100.  *
  101.  * Results:
  102.  *    A pointer to the new VidStream structure.
  103.  *
  104.  * Side effects:
  105.  *      None.
  106.  *
  107.  *--------------------------------------------------------------
  108.  */
  109.  
  110. VidStream * NewVidStream(int bufLength)
  111. {
  112.   int i,j;
  113.   short *intra_quant_matrix, *intra_quant_matrix0, *intra_quant_matrix1;
  114.   VidStream *new;
  115.   static unsigned char default_intra_matrix[64] = {
  116.     8, 16, 19, 22, 26, 27, 29, 34,
  117.     16, 16, 22, 24, 27, 29, 34, 37,
  118.     19, 22, 26, 27, 29, 34, 34, 38,
  119.     22, 22, 26, 27, 29, 34, 37, 40,
  120.     22, 26, 27, 29, 32, 35, 40, 48,
  121.     26, 27, 29, 32, 35, 40, 48, 58,
  122.     26, 27, 29, 34, 38, 46, 56, 69,
  123.     27, 29, 35, 38, 46, 56, 69, 83};
  124.  
  125.   /* Check for legal buffer length. */
  126.  
  127.   if (bufLength < 4) return NULL;
  128.  
  129.   /* Make buffer length multiple of 4. */
  130.  
  131.   bufLength = (bufLength + 3) >> 2;
  132.  
  133.   /* Allocate memory for new structure. */
  134.  
  135.   new = (VidStream *) malloc(sizeof(VidStream));
  136.  
  137.   /* Initialize pointers to extension and user data. */
  138.  
  139.   new->group.ext_data = new->group.user_data =
  140.     new->picture.extra_info = new->picture.user_data =
  141.     new->picture.ext_data = new->slice.extra_info =
  142.     new->ext_data = new->user_data = NULL;
  143.  
  144.   /* Create default intra matrix and qscale multiplication tables. */
  145.  
  146.   new->intra_quant_matrix_ptr[0] = (short*) malloc(32 * 8*8 * sizeof(short));
  147.   clear64words(intra_quant_matrix = new->intra_quant_matrix_ptr[0]);
  148.   for(j=1; j<32; j++) new->intra_quant_matrix_ptr[j] = (intra_quant_matrix+=64);
  149.  
  150.   intra_quant_matrix0 = intra_quant_matrix = new->intra_quant_matrix_ptr[1];
  151.  
  152.   for(i=0; i<64; i++)
  153.     *intra_quant_matrix++ = default_intra_matrix[zigzag_direct[i]];
  154.  
  155.   for(j=2; j<32; j++)
  156.   {
  157.     intra_quant_matrix1 = new->intra_quant_matrix_ptr[1];
  158.     for(i=0; i<64; i++) *intra_quant_matrix++ = (*intra_quant_matrix0++) + (*intra_quant_matrix1++);
  159.   }
  160.  
  161.   /* Initialize non intra quantization matrix. */
  162.  
  163.   new->non_intra_default = TRUE;
  164.   new->non_intra_quant_matrix_ptr[0] = NULL;
  165.  
  166.   /* Initialize pointers to image spaces. */
  167.  
  168.   new->current = new->past = new->future = NULL;
  169.   for (i = 0; i < RING_BUF_SIZE; i++) new->ring[i] = NULL;
  170.  
  171.   /* Create buffer. */
  172.  
  173.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  174.  
  175.   /*
  176.    * Set max_buf_length to one less than actual length to deal with messy
  177.    * data without proper seq. end codes.
  178.    */
  179.  
  180.   new->max_buf_length = bufLength - 1;
  181.  
  182.   /* Initialize bitstream i/o fields. */
  183.  
  184.   new->bit_offset = 0;
  185.   new->buf_length = 0;
  186.   new->buffer = new->buf_start;
  187.  
  188.   /* display stuff */
  189.  
  190.   new->display_is_initialized = FALSE;
  191.  
  192.   /* Return structure. */
  193.  
  194.   return new;
  195. }
  196.  
  197.  
  198.  
  199. /*
  200.  *--------------------------------------------------------------
  201.  *
  202.  * DestroyVidStream --
  203.  *
  204.  *    Deallocates a VidStream structure.
  205.  *
  206.  * Results:
  207.  *      None.
  208.  *
  209.  * Side effects:
  210.  *    None.
  211.  *
  212.  *--------------------------------------------------------------
  213.  */
  214. void DestroyVidStream(VidStream *astream)
  215. {
  216.   int i;
  217.  
  218.   if (astream->ext_data) free(astream->ext_data);
  219.  
  220.   if (astream->user_data) free(astream->user_data);
  221.  
  222.   if (astream->group.ext_data) free(astream->group.ext_data);
  223.  
  224.   if (astream->group.user_data) free(astream->group.user_data);
  225.  
  226.   if (astream->picture.extra_info) free(astream->picture.extra_info);
  227.  
  228.   if (astream->picture.ext_data) free(astream->picture.ext_data);
  229.  
  230.   if (astream->picture.user_data) free(astream->picture.user_data);
  231.  
  232.   if (astream->slice.extra_info) free(astream->slice.extra_info);
  233.  
  234.   if (astream->buf_start) free(astream->buf_start);
  235.  
  236.   for (i = 0; i < RING_BUF_SIZE; i++) {
  237.     if (astream->ring[i]) {
  238.       DestroyPictImage(astream->ring[i]);
  239.       astream->ring[i] = NULL;
  240.     }
  241.   }
  242.  
  243.   if (!astream->non_intra_default) free(astream->non_intra_quant_matrix_ptr[0]);
  244.  
  245.   if (astream->intra_quant_matrix_ptr[0]) free(astream->intra_quant_matrix_ptr[0]);
  246.  
  247.   free((char *) astream);
  248. }
  249.  
  250.  
  251.  
  252.  
  253. /*
  254.  *--------------------------------------------------------------
  255.  *
  256.  * NewPictImage --
  257.  *
  258.  *    Allocates and initializes a PictImage structure.
  259.  *      The width and height of the image space are passed in
  260.  *      as parameters.
  261.  *
  262.  * Results:
  263.  *    A pointer to the new PictImage structure.
  264.  *
  265.  * Side effects:
  266.  *    None.
  267.  *
  268.  *--------------------------------------------------------------
  269.  */
  270.  
  271. PictImage * NewPictImage(unsigned int width, unsigned int height)
  272. {
  273.   extern int lores;
  274.   PictImage *new;
  275.   int size = (short)width * (short)height;
  276.  
  277.   /* Allocate memory space for new structure. */
  278.  
  279.   new = (PictImage *) malloc(sizeof(PictImage));
  280.  
  281.   /* Allocate memory for image spaces. */
  282.   if (ditherType == FULL_COLOR_DITHER) {
  283.     new->display = (unsigned char *) malloc(lores ? (size << 1) : (size << 2));
  284.   } else {
  285.     new->display = (unsigned char *) malloc(size);
  286.   }
  287.  
  288.   new->luminance = (unsigned char *) malloc(size);
  289.   new->Cr = (unsigned char *) malloc(size >> 2);
  290.   new->Cb = (unsigned char *) malloc(size >> 2);
  291.  
  292.   /* Reset locked flag. */
  293.  
  294.   new->locked = 0;
  295.  
  296.   /* Return pointer to new structure. */
  297.  
  298.   return new;
  299. }
  300.  
  301.  
  302.  
  303. /*
  304.  *--------------------------------------------------------------
  305.  *
  306.  * DestroyPictImage --
  307.  *
  308.  *    Deallocates a PictImage structure.
  309.  *
  310.  * Results:
  311.  *      None.
  312.  *
  313.  * Side effects:
  314.  *    None.
  315.  *
  316.  *--------------------------------------------------------------
  317.  */
  318. void DestroyPictImage(PictImage *apictimage)
  319. {
  320.   if (apictimage->luminance) free(apictimage->luminance);
  321.   if (apictimage->Cr) free(apictimage->Cr);
  322.   if (apictimage->Cb) free(apictimage->Cb);
  323.   if (apictimage->display) free(apictimage->display);
  324.   free(apictimage);
  325. }
  326.  
  327. /*
  328.  *--------------------------------------------------------------
  329.  *
  330.  * mpegInitVidRsrc --
  331.  *
  332.  *      reset first to 1
  333.  *
  334.  * gonna check this thingy out !!!!
  335.  *
  336.  *--------------------------------------------------------------
  337.  */
  338. static int first = 1;
  339.  
  340. void mpegInitVidRsrc(void)
  341. {
  342.     first = 1;
  343. }
  344.  
  345.  
  346. /*
  347.  *--------------------------------------------------------------
  348.  *
  349.  * mpegVidRsrc --
  350.  *
  351.  *      Parses bit stream until MB_QUANTUM number of
  352.  *      macroblocks have been decoded or current slice or
  353.  *      picture ends, whichever comes first. If the start
  354.  *      of a frame is encountered, the frame is time stamped
  355.  *      with the value passed in time_stamp. If the value
  356.  *      passed in buffer is not null, the video stream buffer
  357.  *      is set to buffer and the length of the buffer is
  358.  *      expected in value passed in through length. The current
  359.  *      video stream is set to vid_stream. If vid_stream
  360.  *      is passed as NULL, a new VidStream structure is created
  361.  *      and initialized and used as the current video stream.
  362.  *
  363.  * Results:
  364.  *      A Boolean value is returned - 0 is end of picture or error
  365.  *
  366.  * Side effects:
  367.  *      Bit stream is irreversibly parsed. If a picture is completed,
  368.  *      a function is called to display the frame at the correct time.
  369.  *
  370.  *--------------------------------------------------------------
  371.  */
  372.  
  373. int mpegVidRsrc(TimeStamp time_stamp, VidStream *vid_stream)
  374. {
  375.   unsigned int data;
  376.   int i, status;
  377.  
  378.   /* If vid_stream is null, create new VidStream structure.  MR: ????? */
  379.  
  380.   if (vid_stream == NULL) return 0;
  381.  
  382.   /*
  383.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  384.    * curVidStream and are not passed vid_stream. Also set global bitstream
  385.    * parameters.
  386.    */
  387.  
  388.   curVidStream = vid_stream;
  389.   bitOffset = curVidStream->bit_offset;
  390.   bufLength = curVidStream->buf_length;
  391.   bitBuffer = curVidStream->buffer;
  392.  
  393.   /*
  394.    * If called for the first time, find start code, make sure it is a
  395.    * sequence start code.
  396.    */
  397.  
  398.   if (first) {
  399.     next_start_code();
  400.     if (show_bits32(data) != SEQ_START_CODE) {
  401.       fprintf(stderr, "This is not an MPEG stream.\n");
  402.       DestroyVidStream(curVidStream);
  403.       exit(1);
  404.     }
  405.     first = 0;
  406.   }
  407.  
  408.  
  409.   /* Get next 32 bits (size of start codes). */
  410.  
  411.   show_bits32(data);
  412.  
  413.   /*
  414.    * Process according to start code (or parse macroblock if not a start code
  415.    * at all.
  416.    */
  417.  
  418.   switch (data) {
  419.  
  420.   case SEQ_END_CODE:
  421.  
  422.     /* Display last frame. */
  423.  
  424.     if (vid_stream->future != NULL) {
  425.       vid_stream->current = vid_stream->future;
  426.       ExecuteDisplay(vid_stream);
  427.     }
  428.     
  429.     /* Sequence done. Do the right thing. return False. */
  430.  
  431.     if (!quietFlag) {
  432.       fprintf(stderr, "\nDone!\n");
  433.     }
  434.  
  435. #ifdef ANALYSIS
  436.     PrintAllStats();
  437. #endif
  438.     PrintTimeInfo();
  439.  
  440.     if (loopFlag) longjmp(env, 1);
  441.  
  442.     DestroyVidStream(curVidStream);
  443.     return 0;
  444.     break;
  445.  
  446.   case SEQ_START_CODE:
  447.  
  448.     /* Sequence start code. Parse sequence header. */
  449.  
  450.     if (ParseSeqHead(vid_stream) != PARSE_OK) goto error;
  451.  
  452.     /*
  453.      * Return after sequence start code so that application above can use
  454.      * info in header.
  455.      */
  456.  
  457.     goto done;
  458.  
  459.   case GOP_START_CODE:
  460.  
  461.     /* Group of Pictures start code. Parse gop header. */
  462.  
  463.     if (ParseGOP(vid_stream) != PARSE_OK) goto error;
  464.  
  465.  
  466.   case PICTURE_START_CODE:
  467.  
  468.     /* Picture start code. Parse picture header and first slice header. */
  469.  
  470.     status = ParsePicture(vid_stream, time_stamp);
  471.  
  472.     if (status == SKIP_PICTURE) {
  473.       next_start_code();
  474.       fprintf(stderr, "Skipping picture...");
  475.       while ((show_bits32(data)) != PICTURE_START_CODE) {
  476.     if (data == GOP_START_CODE || data == SEQ_END_CODE)
  477.       break;
  478.     flush_bits(24);
  479.     next_start_code();
  480.       }
  481.       fprintf(stderr, "Done.\n");
  482.       goto done;
  483.     } else if (status != PARSE_OK) goto error;
  484.  
  485.  
  486.     if (ParseSlice(vid_stream) != PARSE_OK) goto error;
  487.     break;
  488.  
  489.   default:
  490.  
  491.     /* Check for slice start code. */
  492.  
  493.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE))
  494.       if (ParseSlice(vid_stream) != PARSE_OK)    /* Slice start code. Parse slice header. */
  495.     goto error;
  496.  
  497.     break;
  498.   }
  499.  
  500.   /* Parse next MB_QUANTUM macroblocks. */
  501.  
  502.   for (i = 0; i < MB_QUANTUM; i++) {
  503.  
  504.     /* Check to see if actually a startcode and not a macroblock. */
  505.  
  506.     if ((show_bitsn(23,data)) != 0x00000000) {
  507.  
  508.       /* Not start code. Parse Macroblock. */
  509.  
  510.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  511.     goto error;
  512.  
  513. #ifdef ANALYSIS
  514.       if (showmb_flag) {
  515.     DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  516.               vid_stream->current->Cb, vid_stream->current->display,
  517.               vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  518.     ExecuteDisplay(vid_stream);
  519.       }
  520. #endif
  521.  
  522.     } else {
  523.  
  524.       /* Not macroblock, actually start code. Get start code. */
  525.  
  526.       next_start_code();
  527.       show_bits32(data);
  528.  
  529.       /*
  530.        * If start code is outside range of slice start codes, frame is
  531.        * complete, display frame.
  532.        */
  533.  
  534.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  535.  
  536. #ifdef ANALYSIS
  537.     EndTime();
  538.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  539.     if (showEachFlag)
  540.       PrintOneStat();
  541.  
  542.     CollectStats();
  543. #endif
  544.  
  545.     DoPictureDisplay(vid_stream);
  546.       }
  547.       break;
  548.     }
  549.   }
  550.  
  551.   /* Return pointer to video stream structure. */
  552.  
  553.   goto done;
  554.  
  555. error:
  556.   fprintf(stderr, "Error!!!!\n");
  557.   next_start_code();
  558.   goto done;
  559.  
  560. done:
  561.  
  562.   /* Copy global bit i/o variables back into vid_stream. */
  563.  
  564.   vid_stream->buffer = bitBuffer;
  565.   vid_stream->buf_length = bufLength;
  566.   vid_stream->bit_offset = bitOffset;
  567.  
  568.   return 1;
  569. }
  570.  
  571.  
  572. /*
  573.  *--------------------------------------------------------------
  574.  *
  575.  * ParseSeqHead --
  576.  *
  577.  *      Assumes bit stream is at the begining of the sequence
  578.  *      header start code. Parses off the sequence header.
  579.  *
  580.  * Results:
  581.  *      Fills the vid_stream structure with values derived and
  582.  *      decoded from the sequence header. Allocates the pict image
  583.  *      structures based on the dimensions of the image space
  584.  *      found in the sequence header.
  585.  *
  586.  * Side effects:
  587.  *      Bit stream irreversibly parsed off.
  588.  *
  589.  *--------------------------------------------------------------
  590.  */
  591.  
  592. static int ParseSeqHead(VidStream *vid_stream)
  593. {
  594.   unsigned int data;
  595.   int i;
  596.  
  597.   /* Flush off sequence start code. */
  598.  
  599.   flush_bits32;
  600.  
  601.   /* Get horizontal size of image space. */
  602.  
  603.   get_bits12(vid_stream->h_size);
  604.  
  605.   /* Get vertical size of image space. */
  606.  
  607.   get_bits12(vid_stream->v_size);
  608.  
  609.   /* Calculate macroblock width and height of image space. */
  610.  
  611.   vid_stream->mb_width = (vid_stream->h_size + 15) >> 4;
  612.   vid_stream->mb_height = (vid_stream->v_size + 15) >> 4;
  613.  
  614.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  615.  
  616.   lmaxx = (vid_stream->mb_width<<4)-1;
  617.   lmaxy = (vid_stream->mb_height<<4)-1;
  618.   cmaxx = (vid_stream->mb_width<<3)-1;
  619.   cmaxy = (vid_stream->mb_height<<3)-1;
  620.  
  621.   /*
  622.    * Initialize ring buffer of pict images now that dimensions of image space
  623.    * are known.
  624.    */
  625.  
  626.   if (vid_stream->ring[0] == NULL) {
  627.     for (i = 0; i < RING_BUF_SIZE; i++)
  628.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width << 4, vid_stream->mb_height << 4);
  629.   }
  630.  
  631.   /* Parse of aspect ratio code. */
  632.  
  633.   get_bits4(vid_stream->aspect_ratio);
  634.  
  635.   /* Parse off picture rate code. */
  636.  
  637.   get_bits4(vid_stream->picture_rate);
  638.  
  639.   /* Parse off bit rate. */
  640.  
  641.   get_bits18(vid_stream->bit_rate);
  642.  
  643.   /* Flush marker bit. */
  644.  
  645.   flush_bits(1);
  646.  
  647.   /* Parse off vbv buffer size. */
  648.  
  649.   get_bits10(vid_stream->vbv_buffer_size);
  650.  
  651.   /* Parse off contrained parameter flag. */
  652.  
  653.   get_bits1(vid_stream->const_param_flag);
  654.  
  655.   /*
  656.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  657.    */
  658.  
  659.   if (get_bits1(data))
  660.     new_matrix(vid_stream->intra_quant_matrix_ptr[1]);
  661.  
  662.   /*
  663.    * If non intra quant matrix flag set, parse off non intra quant matrix
  664.    * values.
  665.    */
  666.  
  667.   if (get_bits1(data))
  668.   {
  669.     if(vid_stream->non_intra_default)
  670.     {
  671.     unsigned short *intra_quant_matrix;
  672.  
  673.     vid_stream->non_intra_quant_matrix_ptr[0] = (short*) malloc(32 * 8*8 * sizeof(short));
  674.     clear64words(intra_quant_matrix = vid_stream->non_intra_quant_matrix_ptr[0]);
  675.     for(i=1; i<32; i++) vid_stream->non_intra_quant_matrix_ptr[i] = (intra_quant_matrix+=64);
  676.  
  677.     vid_stream->non_intra_default = FALSE;
  678.     }
  679.  
  680.     new_matrix(vid_stream->non_intra_quant_matrix_ptr[1]);
  681.   }
  682.  
  683.   /* Go to next start code. */
  684.  
  685.   next_start_code();
  686.  
  687.   /*
  688.    * If next start code is extension start code, parse off extension data.
  689.    */
  690.  
  691.   if ((show_bits32(data)) == EXT_START_CODE) {
  692.     flush_bits32;
  693.     if (vid_stream->ext_data) {
  694.       free(vid_stream->ext_data);
  695.       vid_stream->ext_data = NULL;
  696.     }
  697.     vid_stream->ext_data = get_ext_data();
  698.   }
  699.  
  700.   /* If next start code is user start code, parse off user data. */
  701.  
  702.   if ((show_bits32(data)) == USER_START_CODE) {
  703.     flush_bits32;
  704.     if (vid_stream->user_data) {
  705.       free(vid_stream->user_data);
  706.       vid_stream->user_data = NULL;
  707.     }
  708.     vid_stream->user_data = get_ext_data();
  709.   }
  710.   return PARSE_OK;
  711. }
  712.  
  713.  
  714.  
  715. /*
  716.  *--------------------------------------------------------------
  717.  *
  718.  * ParseGOP --
  719.  *
  720.  *      Parses of group of pictures header from bit stream
  721.  *      associated with vid_stream.
  722.  *
  723.  * Results:
  724.  *      Values in gop header placed into video stream structure.
  725.  *
  726.  * Side effects:
  727.  *      Bit stream irreversibly parsed.
  728.  *
  729.  *--------------------------------------------------------------
  730.  */
  731.  
  732. static int ParseGOP(VidStream *vid_stream)
  733. {
  734.   unsigned int data;
  735.  
  736.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  737.  
  738.   flush_bits32;
  739.  
  740.   /* Parse off drop frame flag. */
  741.  
  742.   get_bits1(vid_stream->group.drop_flag);
  743.  
  744.   /* Parse off hour component of time code. */
  745.  
  746.   get_bits5(vid_stream->group.tc_hours);
  747.  
  748.   /* Parse off minute component of time code. */
  749.  
  750.   get_bits6(vid_stream->group.tc_minutes);
  751.  
  752.   /* Flush marker bit. */
  753.  
  754.   flush_bits(1);
  755.  
  756.   /* Parse off second component of time code. */
  757.  
  758.   get_bits6(vid_stream->group.tc_seconds);
  759.  
  760.   /* Parse off picture count component of time code. */
  761.  
  762.   get_bits6(vid_stream->group.tc_pictures);
  763.  
  764.   /* Parse off closed gop and broken link flags. */
  765.  
  766.   get_bits1(vid_stream->group.closed_gop);
  767.   get_bits1(vid_stream->group.broken_link);
  768.  
  769.   /* Goto next start code. */
  770.  
  771.   next_start_code();
  772.  
  773.   /* If next start code is extension data, parse off extension data. */
  774.  
  775.   if ((show_bits32(data)) == EXT_START_CODE) {
  776.     flush_bits32;
  777.     if (vid_stream->group.ext_data) {
  778.       free(vid_stream->group.ext_data);
  779.       vid_stream->group.ext_data = NULL;
  780.     }
  781.     vid_stream->group.ext_data = get_ext_data();
  782.   }
  783.   /* If next start code is user data, parse off user data. */
  784.  
  785.   if ((show_bits32(data)) == USER_START_CODE) {
  786.     flush_bits32;
  787.     if (vid_stream->group.user_data) {
  788.       free(vid_stream->group.user_data);
  789.       vid_stream->group.user_data = NULL;
  790.     }
  791.     vid_stream->group.user_data = get_ext_data();
  792.   }
  793.   return PARSE_OK;
  794. }
  795.  
  796.  
  797.  
  798. /*
  799.  *--------------------------------------------------------------
  800.  *
  801.  * ParsePicture --
  802.  *
  803.  *      Parses picture header. Marks picture to be presented
  804.  *      at particular time given a time stamp.
  805.  *
  806.  * Results:
  807.  *      Values from picture header put into video stream structure.
  808.  *
  809.  * Side effects:
  810.  *      Bit stream irreversibly parsed.
  811.  *
  812.  *--------------------------------------------------------------
  813.  */
  814.  
  815. static int ParsePicture(VidStream *vid_stream, TimeStamp time_stamp)
  816. {
  817.   unsigned int data;
  818.   int i;
  819.  
  820.   /* Flush header start code. */
  821.   flush_bits32;
  822.  
  823.   /* Parse off temporal reference. */
  824.   get_bits10(vid_stream->picture.temp_ref);
  825.  
  826.   /* Parse of picture type. */
  827.   get_bits3(vid_stream->picture.code_type);
  828.  
  829.   if ((vid_stream->picture.code_type == B_TYPE) &&
  830.       (No_B_Flag ||
  831.        (vid_stream->past == NULL) ||
  832.        (vid_stream->future == NULL)))
  833.     return SKIP_PICTURE;
  834.  
  835.   if ((vid_stream->picture.code_type == P_TYPE) &&
  836.       (No_P_Flag || (vid_stream->future == NULL)))
  837.     return SKIP_PICTURE;
  838.  
  839. #ifdef ANALYSIS
  840.   StartTime();
  841.   stat_a[0].frametype = vid_stream->picture.code_type;
  842.   stat_a[0].number = 1;
  843.   stat_a[0].totsize = 45;
  844.   pictureSizeCount = bitCountRead();
  845. #endif
  846.  
  847.   /* Parse off vbv buffer delay value. */
  848.   get_bits16(vid_stream->picture.vbv_delay);
  849.  
  850.   /* If P or B type frame... */
  851.  
  852.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  853.  
  854.     /* Parse off forward vector full pixel flag. */
  855.     get_bits1(vid_stream->picture.full_pel_forw_vector);
  856.  
  857.     /* Parse of and decode forw_r_code into forw_r_size and forw_f. */
  858.  
  859.     get_bits3(vid_stream->picture.forw_r_size) - 1;
  860.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  861.   }
  862.   /* If B type frame... */
  863.  
  864.   if (vid_stream->picture.code_type == 3) {
  865.  
  866.     /* Parse off back vector full pixel flag. */
  867.     get_bits1(vid_stream->picture.full_pel_back_vector);
  868.  
  869.     /* Parse off and decode back_r_code into back_r_size and back_f. */
  870.  
  871.     get_bits3(vid_stream->picture.back_r_size) - 1;
  872.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  873.   }
  874.   /* Get extra bit picture info. */
  875.  
  876.   if (vid_stream->picture.extra_info) {
  877.     free(vid_stream->picture.extra_info);
  878.     vid_stream->picture.extra_info = NULL;
  879.   }
  880.   vid_stream->picture.extra_info = get_extra_bit_info();
  881.  
  882.   /* Goto next start code. */
  883.   next_start_code();
  884.  
  885.   /* If start code is extension start code, parse off extension data. */
  886.  
  887.   if ((show_bits32(data)) == EXT_START_CODE) {
  888.     flush_bits32;
  889.  
  890.     if (vid_stream->picture.ext_data) {
  891.       free(vid_stream->picture.ext_data);
  892.       vid_stream->picture.ext_data = NULL;
  893.     }
  894.     vid_stream->picture.ext_data = get_ext_data();
  895.   }
  896.   /* If start code is user start code, parse off user data. */
  897.  
  898.   if ((show_bits32(data)) == USER_START_CODE) {
  899.     flush_bits32;
  900.  
  901.     if (vid_stream->picture.user_data) {
  902.       free(vid_stream->picture.user_data);
  903.       vid_stream->picture.user_data = NULL;
  904.     }
  905.     vid_stream->picture.user_data = get_ext_data();
  906.   }
  907.   /* Find a pict image structure in ring buffer not currently locked. */
  908.  
  909.   i = 0;
  910.  
  911.   while (vid_stream->ring[i]->locked != 0) {
  912.     if (++i >= RING_BUF_SIZE) {
  913.       perror("Fatal error. Ring buffer full.");
  914.       exit(1);
  915.     }
  916.   }
  917.  
  918.   /* Set current pict image structure to the one just found in ring. */
  919.  
  920.   vid_stream->current = vid_stream->ring[i];
  921.  
  922.   /* Set time stamp. */
  923.  
  924.   vid_stream->current->show_time = time_stamp;
  925.  
  926.   /* Reset past macroblock address field. */
  927.  
  928.   vid_stream->mblock.past_mb_addr = -1;
  929.  
  930.   return PARSE_OK;
  931. }
  932.  
  933.  
  934.  
  935. /*
  936.  *--------------------------------------------------------------
  937.  *
  938.  * ParseSlice --
  939.  *
  940.  *      Parses off slice header.
  941.  *
  942.  * Results:
  943.  *      Values found in slice header put into video stream structure.
  944.  *
  945.  * Side effects:
  946.  *      Bit stream irreversibly parsed.
  947.  *
  948.  *--------------------------------------------------------------
  949.  */
  950.  
  951. static int ParseSlice(VidStream *vid_stream)
  952. {
  953.   /* Flush slice start code. */
  954.  
  955.   flush_bits(24);
  956.  
  957.   /* Parse off slice vertical position. */
  958.  
  959.   get_bits8(vid_stream->slice.vert_pos);
  960.  
  961.   /* Parse off quantization scale. */
  962.  
  963.   get_bits5(vid_stream->slice.quant_scale);
  964.  
  965.   /* Parse off extra bit slice info. */
  966.  
  967.   if (vid_stream->slice.extra_info) {
  968.     free(vid_stream->slice.extra_info);
  969.     vid_stream->slice.extra_info = NULL;
  970.   }
  971.   vid_stream->slice.extra_info = get_extra_bit_info();
  972.  
  973.   /* Reset past intrablock address. */
  974.  
  975.   vid_stream->mblock.past_intra_addr = -2;
  976.  
  977.   /* Reset previous recon motion vectors. */
  978.  
  979.   vid_stream->mblock.recon_right_for_prev = 0;
  980.   vid_stream->mblock.recon_down_for_prev = 0;
  981.   vid_stream->mblock.recon_right_back_prev = 0;
  982.   vid_stream->mblock.recon_down_back_prev = 0;
  983.  
  984.   /* Reset macroblock address. */
  985.  
  986.   vid_stream->mblock.mb_address = ((short)(vid_stream->slice.vert_pos - 1) * (short)vid_stream->mb_width) - 1;
  987.  
  988.   /* Reset past dct dc y, cr, and cb values. */
  989.  
  990.   vid_stream->block.dct_dc_y_past = 1024;
  991.   vid_stream->block.dct_dc_cr_past = 1024;
  992.   vid_stream->block.dct_dc_cb_past = 1024;
  993.  
  994.   return PARSE_OK;
  995. }
  996.  
  997.  
  998.  
  999. /*
  1000.  *--------------------------------------------------------------
  1001.  *
  1002.  * ParseMacroBlock --
  1003.  *
  1004.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1005.  *      inverse DCT, reconstructs motion vectors, calculates and
  1006.  *      set pixel values for macroblock in current pict image
  1007.  *      structure.
  1008.  *
  1009.  * Results:
  1010.  *      Here's where everything really happens. Welcome to the
  1011.  *      heart of darkness.
  1012.  *
  1013.  * Side effects:
  1014.  *      Bit stream irreversibly parsed off.
  1015.  *
  1016.  *--------------------------------------------------------------
  1017.  */
  1018.  
  1019. static int ParseMacroBlock(VidStream *vid_stream)
  1020. {
  1021.     int addr_incr, mask, i;
  1022.     int recon_right_for, recon_down_for, recon_right_back, recon_down_back, zero_block_flag;
  1023.     int mb_data;
  1024.  
  1025. #ifdef ANALYSIS
  1026.     mbSizeCount = bitCountRead();
  1027. #endif
  1028.  
  1029.     /*
  1030.      * Parse off macroblock address increment and add to macroblock address.
  1031.      */
  1032.     do {
  1033.         DecodeMBAddrInc(addr_incr);
  1034.         if (addr_incr == MB_ESCAPE) {
  1035.             vid_stream->mblock.mb_address += 33;
  1036.             addr_incr = MB_STUFFING;
  1037.         }
  1038.     } while (addr_incr == MB_STUFFING);
  1039.     vid_stream->mblock.mb_address += addr_incr;
  1040.  
  1041.     if (vid_stream->mblock.mb_address > ((short)vid_stream->mb_height * (short)vid_stream->mb_width - 1))
  1042.         return SKIP_TO_START_CODE;
  1043.  
  1044.     /*
  1045.      * If macroblocks have been skipped, process skipped macroblocks.
  1046.      */
  1047.  
  1048.     if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1049.         if (vid_stream->picture.code_type == P_TYPE)
  1050.             ProcessSkippedPFrameMBlocks(vid_stream);
  1051.         else if (vid_stream->picture.code_type == B_TYPE)
  1052.             ProcessSkippedBFrameMBlocks(vid_stream);
  1053.     }
  1054.  
  1055.     /* Set past macroblock address to current macroblock address. */
  1056.     vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1057.  
  1058.     /* Based on picture type decode macroblock type. */
  1059.     switch (vid_stream->picture.code_type) {
  1060.         case I_TYPE:
  1061.             DecodeMBTypeI(mb_data, vid_stream->mblock.mb_intra);
  1062.             break;
  1063.         case P_TYPE:
  1064.             DecodeMBTypeP(mb_data, vid_stream->mblock.mb_intra);
  1065.             break;
  1066.         case B_TYPE:
  1067.             DecodeMBTypeB(mb_data, vid_stream->mblock.mb_intra);
  1068.             break;
  1069.     }
  1070.  
  1071.     /* If quantization flag set, parse off new quantization scale. */
  1072.     if (mb_data&MB_quant) {
  1073.         get_bits5(vid_stream->slice.quant_scale);
  1074.     }
  1075.  
  1076.   /* If forward motion vectors exist... */
  1077.   if (mb_data&MB_motion_forw) {
  1078.  
  1079.     /* Parse off and decode horizontal forward motion vector. */
  1080.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1081.  
  1082.     /* If horiz. forward r data exists, parse off. */
  1083.  
  1084.     if ((vid_stream->picture.forw_f != 1) && (vid_stream->mblock.motion_h_forw_code != 0)) {
  1085.       get_bitsn(vid_stream->picture.forw_r_size, vid_stream->mblock.motion_h_forw_r);
  1086.     }
  1087.     /* Parse off and decode vertical forward motion vector. */
  1088.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1089.  
  1090.     /* If vert. forw. r data exists, parse off. */
  1091.  
  1092.     if ((vid_stream->picture.forw_f != 1) && (vid_stream->mblock.motion_v_forw_code != 0)) {
  1093.       get_bitsn(vid_stream->picture.forw_r_size, vid_stream->mblock.motion_v_forw_r);
  1094.     }
  1095.   }
  1096.   /* If back motion vectors exist... */
  1097.   if (mb_data&MB_motion_back) {
  1098.  
  1099.     /* Parse off and decode horiz. back motion vector. */
  1100.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1101.  
  1102.     /* If horiz. back r data exists, parse off. */
  1103.  
  1104.     if ((vid_stream->picture.back_f != 1) && (vid_stream->mblock.motion_h_back_code != 0)) {
  1105.       get_bitsn(vid_stream->picture.back_r_size, vid_stream->mblock.motion_h_back_r);
  1106.     }
  1107.     /* Parse off and decode vert. back motion vector. */
  1108.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1109.  
  1110.     /* If vert. back r data exists, parse off. */
  1111.  
  1112.     if ((vid_stream->picture.back_f != 1) && (vid_stream->mblock.motion_v_back_code != 0)) {
  1113.       get_bitsn(vid_stream->picture.back_r_size, vid_stream->mblock.motion_v_back_r);
  1114.     }
  1115.   }
  1116. #ifdef ANALYSIS
  1117.     if (vid_stream->mblock.mb_intra) {
  1118.         stat_a[0].i_mbnum++;
  1119.         mbCBPPtr = stat_a[0].i_mbcbp;
  1120.         mbCoeffPtr = stat_a[0].i_mbcoeff;
  1121.         mbSizePtr = &(stat_a[0].i_mbsize);
  1122.     } else if ((mb_data&(MB_motion_back | MB_motion_forw)) == (MB_motion_back | MB_motion_forw)) {
  1123.         stat_a[0].bi_mbnum++;
  1124.         mbCBPPtr = stat_a[0].bi_mbcbp;
  1125.         mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1126.         mbSizePtr = &(stat_a[0].bi_mbsize);
  1127.     } else if (mb_data&MB_motion_back) {
  1128.         stat_a[0].b_mbnum++;
  1129.         mbCBPPtr = stat_a[0].b_mbcbp;
  1130.         mbCoeffPtr = stat_a[0].b_mbcoeff;
  1131.         mbSizePtr = &(stat_a[0].b_mbsize);
  1132.     } else {
  1133.         stat_a[0].p_mbnum++;
  1134.         mbCBPPtr = stat_a[0].p_mbcbp;
  1135.         mbCoeffPtr = stat_a[0].p_mbcoeff;
  1136.         mbSizePtr = &(stat_a[0].p_mbsize);
  1137.     }
  1138. #endif
  1139.  
  1140.     /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1141.     if (mb_data&MB_pattern) {
  1142.         DecodeCBP(vid_stream->mblock.cbp);
  1143.     } else /* Otherwise, set CBP to zero. */
  1144.         vid_stream->mblock.cbp = 0;
  1145.  
  1146. #ifdef ANALYSIS
  1147.     mbCBPPtr[vid_stream->mblock.cbp]++;
  1148. #endif
  1149.  
  1150.   /* Reconstruct motion vectors depending on picture type. */
  1151.   if (vid_stream->picture.code_type == P_TYPE) {
  1152.  
  1153.     /*
  1154.      * If no forw motion vectors, reset previous and current vectors to 0.
  1155.      */
  1156.  
  1157.     if (!(mb_data&MB_motion_forw)) {
  1158.       recon_right_for = 0;
  1159.       recon_down_for = 0;
  1160.       vid_stream->mblock.recon_right_for_prev = 0;
  1161.       vid_stream->mblock.recon_down_for_prev = 0;
  1162.     }
  1163.     /*
  1164.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1165.      * current vectors.
  1166.      */
  1167.  
  1168.     else {
  1169.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1170.     }
  1171.   }
  1172.   if (vid_stream->picture.code_type == B_TYPE) {
  1173.  
  1174.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1175.  
  1176.     if (vid_stream->mblock.mb_intra) {
  1177.       vid_stream->mblock.recon_right_for_prev = 0;
  1178.       vid_stream->mblock.recon_down_for_prev = 0;
  1179.       vid_stream->mblock.recon_right_back_prev = 0;
  1180.       vid_stream->mblock.recon_down_back_prev = 0;
  1181.     } else {
  1182.  
  1183.       /* If no forw vectors, current vectors equal prev. vectors. */
  1184.  
  1185.       if (!(mb_data&MB_motion_forw)) {
  1186.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1187.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1188.       }
  1189.       /*
  1190.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1191.        */
  1192.  
  1193.       else {
  1194.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1195.       }
  1196.  
  1197.       /* If no back vectors, set back vectors to prev back vectors. */
  1198.  
  1199.       if (!(mb_data&MB_motion_back)) {
  1200.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1201.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1202.       }
  1203.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1204.  
  1205.       else {
  1206.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1207.       }
  1208.  
  1209.       /*
  1210.        * Store vector existance flags in structure for possible skipped
  1211.        * macroblocks to follow.
  1212.        */
  1213.  
  1214.       if(mb_data<0)
  1215.     vid_stream->mblock.bpict_past_forw = vid_stream->mblock.bpict_past_back = -1;
  1216.       else {
  1217.     vid_stream->mblock.bpict_past_forw = mb_data&MB_motion_forw;
  1218.     vid_stream->mblock.bpict_past_back = mb_data&MB_motion_back;
  1219.       }
  1220.  
  1221.     }
  1222.   }
  1223.  
  1224.   /* For each possible block in macroblock. */
  1225.   if (ditherType == GRAY_DITHER) {
  1226.     for (mask = 32, i = 0; i < 4; mask >>= 1, i++) {
  1227.  
  1228.       /* If block exists... */
  1229.       if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1230.     zero_block_flag = 0;
  1231.     ParseReconBlock(i);
  1232.       } else
  1233.     zero_block_flag = 1;
  1234.  
  1235.       /* If macroblock is intra coded... */
  1236.       if (vid_stream->mblock.mb_intra) {
  1237.     ReconIMBlock(vid_stream, i);
  1238.       } else if ((mb_data&(MB_motion_forw | MB_motion_back)) == (MB_motion_forw | MB_motion_back)) {
  1239.     ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1240.               recon_right_back, recon_down_back, zero_block_flag);
  1241.       } else if ((mb_data&MB_motion_forw) || (vid_stream->picture.code_type == P_TYPE)) {
  1242.     ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1243.              zero_block_flag);
  1244.       } else if (mb_data&MB_motion_back) {
  1245.     ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1246.              zero_block_flag);
  1247.       }
  1248.     }
  1249.     /* Kill the Chrominace blocks... */
  1250.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) ParseAwayBlock(4);
  1251.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) ParseAwayBlock(5);
  1252.   } else {
  1253.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1254.     
  1255.     /* If block exists... */
  1256.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1257.       zero_block_flag = 0;
  1258.       ParseReconBlock(i);
  1259.     } else
  1260.       zero_block_flag = 1;
  1261.     
  1262.     /* If macroblock is intra coded... */
  1263.     if (vid_stream->mblock.mb_intra) {
  1264.       ReconIMBlock(vid_stream, i);
  1265.     } else if ((mb_data&(MB_motion_forw | MB_motion_back)) == (MB_motion_forw | MB_motion_back)) {
  1266.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1267.             recon_right_back, recon_down_back, zero_block_flag);
  1268.     } else if ((mb_data&MB_motion_forw) || (vid_stream->picture.code_type == P_TYPE)) {
  1269.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1270.                zero_block_flag);
  1271.     } else if (mb_data&MB_motion_back) {
  1272.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1273.                zero_block_flag);
  1274.     }
  1275.       }
  1276.   }
  1277.  
  1278.   /* If D Type picture, flush marker bit. */
  1279.   if (vid_stream->picture.code_type == 4) flush_bits(1);
  1280.  
  1281.   /* If macroblock was intracoded, set macroblock past intra address. */
  1282.   if (vid_stream->mblock.mb_intra) vid_stream->mblock.past_intra_addr = vid_stream->mblock.mb_address;
  1283.  
  1284. #ifdef ANALYSIS
  1285.   *mbSizePtr += bitCountRead() - mbSizeCount;
  1286. #endif
  1287.  
  1288.   return PARSE_OK;
  1289. }
  1290.  
  1291.  
  1292.  
  1293. /*MR
  1294.  *--------------------------------------------------------------
  1295.  *
  1296.  * ReconIMBlock --
  1297.  *
  1298.  *    Reconstructs intra coded macroblock.
  1299.  *
  1300.  * Results:
  1301.  *    None.
  1302.  *
  1303.  * Side effects:
  1304.  *    None.
  1305.  *
  1306.  *--------------------------------------------------------------
  1307.  */
  1308.  
  1309. static void ReconIMBlock(VidStream *vid_stream, int bnum)
  1310. {
  1311.   int row, col, row_size;
  1312.   unsigned char *dest;
  1313.  
  1314.   row_size = vid_stream->mb_width;
  1315.   /* Calculate macroblock row and column from address. */
  1316.   row = vid_stream->mblock.mb_address / row_size;
  1317.   col = vid_stream->mblock.mb_address % row_size;
  1318.  
  1319.   /* If block is luminance block... */
  1320.  
  1321.   if (bnum < 4) {
  1322.  
  1323.     /* Calculate row and col values for upper left pixel of block. */
  1324.     row <<= 4;
  1325.     col <<= 4;
  1326.     if (bnum > 1) row += 8;
  1327.     if (bnum & 1) col += 8;
  1328.  
  1329.     /* Set dest to luminance plane of current pict image. */
  1330.     dest = vid_stream->current->luminance;
  1331.  
  1332.     /* Establish row size. */
  1333.     row_size *= 16;
  1334.   }
  1335.   /* Otherwise if block is Cr block... */
  1336.  
  1337.   else if (bnum == 4) {
  1338.  
  1339.     /* Set dest to Cr plane of current pict image. */
  1340.     dest = vid_stream->current->Cr;
  1341.  
  1342.     /* Establish row size. */
  1343.     row_size <<= 3;
  1344.  
  1345.     /* Calculate row,col for upper left pixel of block. */
  1346.     row <<= 3;
  1347.     col <<= 3;
  1348.   }
  1349.   /* Otherwise block is Cb block, and ... */
  1350.  
  1351.   else {
  1352.  
  1353.     /* Set dest to Cb plane of current pict image. */
  1354.     dest = vid_stream->current->Cb;
  1355.  
  1356.     /* Establish row size. */
  1357.     row_size <<= 3;
  1358.  
  1359.     /* Calculate row,col for upper left pixel value of block. */
  1360.     row <<= 3;
  1361.     col <<= 3;
  1362.   }
  1363.  
  1364.   /*
  1365.    * For each pixel in block, set to cropped reconstructed value from inverse dct.
  1366.    */
  1367.   IM_reconstruct(dest + row * row_size + col, &vid_stream->block.dct_recon[0][0], row_size);
  1368. }
  1369.  
  1370.  
  1371.  
  1372. /* MR
  1373.  *--------------------------------------------------------------
  1374.  *
  1375.  * ReconPMBlock --
  1376.  *
  1377.  *    Reconstructs forward predicted macroblocks.
  1378.  *
  1379.  * Results:
  1380.  *      None.
  1381.  *
  1382.  * Side effects:
  1383.  *      None.
  1384.  *
  1385.  *--------------------------------------------------------------
  1386.  */
  1387. static void ReconPMBlock(VidStream *vid_stream, int bnum, int recon_right_for, int recon_down_for, int zflag)
  1388. {
  1389.   int row, col, row_size;
  1390.   unsigned char *dest, *past, *rindex2;
  1391.   int right_half_for, down_half_for;
  1392.  
  1393.   row_size = vid_stream->mb_width;
  1394.   /* Calculate macroblock row and column from address. */
  1395.   row = vid_stream->mblock.mb_address / row_size;
  1396.   col = vid_stream->mblock.mb_address % row_size;
  1397.  
  1398.   if (bnum < 4) {
  1399.     /* Calculate right_for, down_for motion vectors. */
  1400.  
  1401.     right_half_for = recon_right_for & 0x1;
  1402.     down_half_for = recon_down_for & 0x1;
  1403.     recon_right_for >>= 1;
  1404.     recon_down_for >>= 1;
  1405.  
  1406.     /* Set dest to luminance plane of current pict image. */
  1407.     dest = vid_stream->current->luminance;
  1408.  
  1409.     if (vid_stream->picture.code_type == B_TYPE) {
  1410.       if (vid_stream->past) past = vid_stream->past->luminance;
  1411.     } else {
  1412.       /* Set predicitive frame to current future frame. */
  1413.       if (vid_stream->future) past = vid_stream->future->luminance;
  1414.     }
  1415.  
  1416.     /* Establish row size. */
  1417.     row_size <<= 4;
  1418.  
  1419.     /* Calculate row,col of upper left pixel in block. */
  1420.     row <<= 4;
  1421.     col <<= 4;
  1422.     if (bnum > 1) row += 8;
  1423.     if (bnum & 1) col += 8;
  1424.  
  1425.   }
  1426.   /* Otherwise, block is NOT luminance block, ... */
  1427.   else {
  1428.     /* Construct motion vectors. */
  1429.     right_half_for = (recon_right_for & 0x2)>>1;
  1430.     down_half_for = recon_down_for & 0x2;
  1431.     recon_right_for >>= 2;
  1432.     recon_down_for >>= 2;
  1433.  
  1434.     /* Establish row size. */
  1435.     row_size <<= 3;
  1436.  
  1437.     /* Calculate row,col of upper left pixel in block. */
  1438.     row <<= 3;
  1439.     col <<= 3;
  1440.  
  1441.     /* If block is Cr block... */
  1442.  
  1443.     if (bnum == 4) {
  1444.       /* Set dest to Cr plane of current pict image. */
  1445.       dest = vid_stream->current->Cr;
  1446.  
  1447.       if (vid_stream->picture.code_type == B_TYPE) {
  1448.     if (vid_stream->past) past = vid_stream->past->Cr;
  1449.       } else {
  1450.     if (vid_stream->future) past = vid_stream->future->Cr;
  1451.       }
  1452.     }
  1453.     /* Otherwise, block is Cb block... */
  1454.     else {
  1455.       /* Set dest to Cb plane of current pict image. */
  1456.       dest = vid_stream->current->Cb;
  1457.  
  1458.       if (vid_stream->picture.code_type == B_TYPE) {
  1459.     if (vid_stream->past) past = vid_stream->past->Cb;
  1460.       } else {
  1461.     if (vid_stream->future) past = vid_stream->future->Cb;
  1462.       }
  1463.     }
  1464.   }
  1465.  
  1466.   /* For each pixel in block... */
  1467.     dest += ((short)row * (short)row_size) + col;
  1468.     past += (short)(row + recon_down_for) * (short)row_size + col + recon_right_for;
  1469.  
  1470.     /*
  1471.      * Calculate predictive pixel value based on motion vectors and copy to
  1472.      * dest plane.
  1473.      */
  1474.  
  1475.     if ((!down_half_for) && (!right_half_for)) {
  1476.       if (!zflag)
  1477.     BMcm_reconstruct(dest, past, &(vid_stream->block.dct_recon[0][0]), row_size);
  1478.       else
  1479.     BM_reconstruct(dest, past, row_size);
  1480.     } else {
  1481.       rindex2 = past + right_half_for + (down_half_for?row_size:0);
  1482.       if (!zflag)
  1483.     BIMcm_reconstruct(dest, past, rindex2, &(vid_stream->block.dct_recon[0][0]), row_size);
  1484.       else
  1485.     BIM_reconstruct(dest, past, rindex2, row_size);
  1486.     }
  1487.  
  1488. }
  1489.  
  1490.  
  1491. /* MR
  1492.  *--------------------------------------------------------------
  1493.  *
  1494.  * ReconBMBlock --
  1495.  *
  1496.  *    Reconstructs back predicted macroblocks.
  1497.  *
  1498.  * Results:
  1499.  *      None.
  1500.  *
  1501.  * Side effects:
  1502.  *      None.
  1503.  *
  1504.  *--------------------------------------------------------------
  1505.  */
  1506.  
  1507. static void ReconBMBlock(VidStream *vid_stream, int bnum, int recon_right_back, int recon_down_back, int zflag)
  1508. {
  1509.   int row, col, row_size;
  1510.   unsigned char *dest, *future, *rindex2;
  1511.   int right_half_back, down_half_back;
  1512.  
  1513.   row_size = vid_stream->mb_width;
  1514.   /* Calculate macroblock row and column from address. */
  1515.   row = vid_stream->mblock.mb_address / row_size;
  1516.   col = vid_stream->mblock.mb_address % row_size;
  1517.  
  1518.   /* If block is luminance block... */
  1519.  
  1520.   if (bnum < 4) {
  1521.     /* Calculate right_back, down_back motion vectors. */
  1522.     right_half_back = recon_right_back & 0x1;
  1523.     down_half_back = recon_down_back & 0x1;
  1524.     recon_right_back >>= 1;
  1525.     recon_down_back >>= 1;
  1526.  
  1527.     /* Set dest to luminance plane of current pict image. */
  1528.     dest = vid_stream->current->luminance;
  1529.  
  1530.     /* If future frame exists, set future to luminance plane of future frame. */
  1531.     if (vid_stream->future) future = vid_stream->future->luminance;
  1532.  
  1533.     /* Establish row size. */
  1534.     row_size <<= 4;
  1535.  
  1536.     /* Calculate row,col of upper left pixel in block. */
  1537.     row <<= 4;
  1538.     col <<= 4;
  1539.     if (bnum > 1) row += 8;
  1540.     if (bnum & 1) col += 8;
  1541.  
  1542.   }
  1543.   /* Otherwise, block is NOT luminance block, ... */
  1544.   else {
  1545.     /* Construct motion vectors. */
  1546.     right_half_back = (recon_right_back & 0x2)>>1;    /* used as integer down there */
  1547.     down_half_back = recon_down_back & 0x2;
  1548.     recon_right_back >>= 2;
  1549.     recon_down_back >>= 2;
  1550.  
  1551.     /* Establish row size. */
  1552.     row_size <<= 3;
  1553.  
  1554.     /* Calculate row,col of upper left pixel in block. */
  1555.     row <<= 3;
  1556.     col <<= 3;
  1557.  
  1558.     /* If block is Cr block... */
  1559.  
  1560.     if (bnum == 4) {
  1561.       /* Set dest to Cr plane of current pict image. */
  1562.       dest = vid_stream->current->Cr;
  1563.  
  1564.       /* If future frame exists, set future to Cr plane of future image. */
  1565.       if (vid_stream->future) future = vid_stream->future->Cr;
  1566.     }
  1567.     /* Otherwise, block is Cb block... */
  1568.     else {
  1569.       /* Set dest to Cb plane of current pict image. */
  1570.       dest = vid_stream->current->Cb;
  1571.  
  1572.       /* If future frame exists, set future to Cb plane of future frame. */
  1573.       if (vid_stream->future) future = vid_stream->future->Cb;
  1574.     }
  1575.   }
  1576.  
  1577.   /* For each pixel in block do... */
  1578.     dest += ((short)row * (short)row_size) + col;
  1579.     future += (short)(row + recon_down_back) * (short)row_size + col + recon_right_back;
  1580.  
  1581.     if ((!right_half_back) && (!down_half_back)) {
  1582.       if (!zflag)
  1583.     BMcm_reconstruct(dest, future, &(vid_stream->block.dct_recon[0][0]), row_size);
  1584.       else
  1585.     BM_reconstruct(dest, future, row_size);
  1586.     } else {
  1587.       rindex2 = future + right_half_back + (down_half_back?row_size:0);
  1588.       if (!zflag)
  1589.     BIMcm_reconstruct(dest, future, rindex2, &(vid_stream->block.dct_recon[0][0]), row_size);
  1590.       else
  1591.     BIM_reconstruct(dest, future, rindex2, row_size);
  1592.     }
  1593. }
  1594.  
  1595.  
  1596. /* MR
  1597.  *--------------------------------------------------------------
  1598.  *
  1599.  * ReconBiMBlock --
  1600.  *
  1601.  *    Reconstructs bidirectionally predicted macroblocks.
  1602.  *
  1603.  * Results:
  1604.  *      None.
  1605.  *
  1606.  * Side effects:
  1607.  *      None.
  1608.  *
  1609.  *--------------------------------------------------------------
  1610.  */
  1611.  
  1612. static void ReconBiMBlock(VidStream *vid_stream, int bnum,
  1613.               int forw_col_start, int forw_row_start,
  1614.               int back_col_start, int back_row_start,
  1615.               int zflag)
  1616. {
  1617.   int row, col, row_size;
  1618.   unsigned char *dest, *past, *future;
  1619.  
  1620.   row_size = vid_stream->mb_width;
  1621.   /* Calculate macroblock row and column from address. */
  1622.   row = vid_stream->mblock.mb_address / row_size;
  1623.   col = vid_stream->mblock.mb_address % row_size;
  1624.  
  1625.   /* If block is luminance block... */
  1626.  
  1627.   if (bnum < 4) {
  1628.     /* Set dest to luminance plane of current pict image. */
  1629.     dest = vid_stream->current->luminance;
  1630.  
  1631.     /* If past frame exists, set past to luminance plane of past frame. */
  1632.     if (vid_stream->past) past = vid_stream->past->luminance;
  1633.  
  1634.     /*If future frame exists, set future to luminance plane of future frame. */
  1635.     if (vid_stream->future) future = vid_stream->future->luminance;
  1636.  
  1637.     /* Establish row size. */
  1638.     row_size <<= 4;
  1639.  
  1640.     /* Calculate row,col of upper left pixel in block. */
  1641.     row <<= 4;
  1642.     col <<= 4;
  1643.     if (bnum > 1) row += 8;
  1644.     if (bnum & 1) col += 8;
  1645.  
  1646.     forw_col_start = (forw_col_start>>1) + col;
  1647.     forw_row_start = (forw_row_start>>1) + row;
  1648.     back_col_start = (back_col_start>>1) + col;
  1649.     back_row_start = (back_row_start>>1) + row;
  1650.  
  1651.   }
  1652.   /* Otherwise, block is NOT luminance block, ... */
  1653.  
  1654.   else {
  1655.     /* Establish row size. */
  1656.     row_size <<= 3;
  1657.  
  1658.     /* Calculate row,col of upper left pixel in block. */
  1659.     row <<= 3;
  1660.     col <<= 3;
  1661.  
  1662.     forw_col_start = (forw_col_start>>2) + col;
  1663.     forw_row_start = (forw_row_start>>2) + row;
  1664.     back_col_start = (back_col_start>>2) + col;
  1665.     back_row_start = (back_row_start>>2) + row;
  1666.  
  1667.     /* If block is Cr block... */
  1668.  
  1669.     if (bnum == 4) {
  1670.       /* Set dest to Cr plane of current pict image. */
  1671.       dest = vid_stream->current->Cr;
  1672.  
  1673.       /* If past frame exists, set past to Cr plane of past image. */
  1674.       if (vid_stream->past) past = vid_stream->past->Cr;
  1675.  
  1676.       /* If future frame exists, set future to Cr plane of future image. */
  1677.       if (vid_stream->future) future = vid_stream->future->Cr;
  1678.     }
  1679.     /* Otherwise, block is Cb block... */
  1680.  
  1681.     else {
  1682.       /* Set dest to Cb plane of current pict image. */
  1683.       dest = vid_stream->current->Cb;
  1684.  
  1685.       /* If past frame exists, set past to Cb plane of past frame. */
  1686.       if (vid_stream->past) past = vid_stream->past->Cb;
  1687.  
  1688.       /* If future frame exists, set future to Cb plane of future frame. */
  1689.       if (vid_stream->future) future = vid_stream->future->Cb;
  1690.     }
  1691.   }
  1692.  
  1693.   dest += (short)row * (short)row_size + col;
  1694.   past += (short)forw_row_start  * (short)row_size + forw_col_start;
  1695.   future += (short)back_row_start * (short)row_size + back_col_start;
  1696.  
  1697.   if (!zflag)
  1698.     BIMcm_reconstruct(dest, past, future, &(vid_stream->block.dct_recon[0][0]), row_size);
  1699.   else
  1700.     BIM_reconstruct(dest, past, future, row_size);
  1701. }
  1702.  
  1703. /* MR
  1704.  *--------------------------------------------------------------
  1705.  *
  1706.  * ProcessSkippedPFrameMBlocks --
  1707.  *
  1708.  *    Processes skipped macroblocks in P frames.
  1709.  *
  1710.  * Results:
  1711.  *    Calculates pixel values for luminance, Cr, and Cb planes
  1712.  *      in current pict image for skipped macroblocks.
  1713.  *
  1714.  * Side effects:
  1715.  *    Pixel values in pict image changed.
  1716.  *
  1717.  *--------------------------------------------------------------
  1718.  */
  1719.  
  1720. static void ProcessSkippedPFrameMBlocks(VidStream *vid_stream)
  1721. {
  1722.   int row_size, row, col, addr, off;
  1723.  
  1724.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  1725.  
  1726.   row_size = vid_stream->mb_width << 4;
  1727.  
  1728.   /* For each skipped macroblock, do... */
  1729.  
  1730.   addr = vid_stream->mblock.past_mb_addr + 1;
  1731.   row = (addr / vid_stream->mb_width)<<4;
  1732.   col = (addr % vid_stream->mb_width)<<4;
  1733.  
  1734.   for (; addr < vid_stream->mblock.mb_address; addr++, col+=16) {
  1735.  
  1736.     /* Calculate macroblock row and col. */
  1737.     if(col>=row_size) col=0, row+=16;
  1738.  
  1739.     /* For each row in macroblock luminance plane... */
  1740.  
  1741.     off = ((short)row * (short)row_size);
  1742.     PMB1_reconstruct(vid_stream->current->luminance + off + col,
  1743.              vid_stream->future->luminance + off + col,
  1744.              row_size >> 2);
  1745.  
  1746.     /* For each row in Cr, and Cb planes... */
  1747.  
  1748.     off >>= 2;
  1749.     off += (col>>1);
  1750.     PMB2_reconstruct(vid_stream->current->Cr + off,
  1751.              vid_stream->current->Cb + off,
  1752.              vid_stream->future->Cr + off,
  1753.              vid_stream->future->Cb + off,
  1754.              row_size >> 3);
  1755.   }
  1756.  
  1757.   vid_stream->mblock.recon_right_for_prev = 0;
  1758.   vid_stream->mblock.recon_down_for_prev = 0;
  1759. }
  1760.  
  1761.  
  1762.  
  1763.  
  1764. /* MR
  1765.  *--------------------------------------------------------------
  1766.  *
  1767.  * ProcessSkippedBFrameMBlocks --
  1768.  *
  1769.  *    Processes skipped macroblocks in B frames.
  1770.  *
  1771.  * Results:
  1772.  *    Calculates pixel values for luminance, Cr, and Cb planes
  1773.  *      in current pict image for skipped macroblocks.
  1774.  *
  1775.  * Side effects:
  1776.  *    Pixel values in pict image changed.
  1777.  *
  1778.  *--------------------------------------------------------------
  1779.  */
  1780.  
  1781. static void ProcessSkippedBFrameMBlocks(VidStream *vid_stream)
  1782. {
  1783.   int row_size, half_row, row, col, ccol, crow;
  1784.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  1785.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  1786.   int addr;
  1787.   int recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  1788.   int c_right_for, c_down_for, c_right_back, c_down_back;
  1789.   unsigned char forw_lum[256];
  1790.   unsigned char forw_cr[64], forw_cb[64];
  1791.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  1792.   int row_incr, half_row_incr;
  1793.   int h;
  1794.   char *lum;
  1795.  
  1796.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  1797.  
  1798.   row_size = vid_stream->mb_width << 4;
  1799.   half_row = row_size >> 1;
  1800.   row_incr = row_size >> 2;
  1801.   half_row_incr =  half_row >> 2;
  1802.  
  1803.   /* Establish motion vector codes based on full pixel flag. */
  1804.  
  1805.   recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1806.   recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1807.   if (vid_stream->picture.full_pel_forw_vector) {
  1808.     recon_right_for <<= 1;
  1809.     recon_down_for <<= 1;
  1810.   }
  1811.  
  1812.   recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1813.   recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1814.   if (vid_stream->picture.full_pel_back_vector) {
  1815.     recon_right_back <<=1;
  1816.     recon_down_back <<=1;
  1817.   }
  1818.  
  1819.  
  1820.   /* If only one motion vector, do display copy, else do full
  1821.      calculation. 
  1822.   */
  1823.   /* Calculate motion vectors. */
  1824.   
  1825.   if (vid_stream->mblock.bpict_past_forw) {
  1826.     right_half_for = recon_right_for & 0x1;
  1827.     down_half_for = recon_down_for & 0x1;
  1828.     recon_right_for >>= 1;
  1829.     recon_down_for >>= 1;
  1830.     c_right_for = recon_right_for >> 1;
  1831.     c_down_for = recon_down_for >> 1;
  1832.     c_right_half_for = recon_right_for & 0x1;
  1833.     c_down_half_for = recon_down_for & 0x1;
  1834.     
  1835.   }
  1836.   if (vid_stream->mblock.bpict_past_back) {
  1837.     right_half_back = recon_right_back & 0x1;
  1838.     down_half_back = recon_down_back & 0x1;    
  1839.     recon_right_back >>= 1;
  1840.     recon_down_back >>= 1;
  1841.     c_right_back = recon_right_back >> 1;
  1842.     c_down_back = recon_down_back >> 1;
  1843.     c_right_half_back = recon_right_back & 0x1;
  1844.     c_down_half_back = recon_down_back & 0x1;
  1845.     
  1846.   }
  1847.   /* For each skipped macroblock, do... */
  1848.   addr = vid_stream->mblock.past_mb_addr + 1;
  1849.   row = (addr / vid_stream->mb_width)<<4;
  1850.   col = (addr % vid_stream->mb_width)<<4;
  1851.  
  1852.   for (; addr < vid_stream->mblock.mb_address; addr++, col+=16) {
  1853.     
  1854.     /* Calculate macroblock row and col. */
  1855.     if(col>=row_size) col=0, row+=16;
  1856.  
  1857.     /* Calculate upper left pixel row,col for luminance plane. */
  1858.     crow = row >> 1;
  1859.     ccol = col >> 1;
  1860.     
  1861.     /* If forward predicted, calculate prediction values. */
  1862.     
  1863.     if (vid_stream->mblock.bpict_past_forw) {
  1864.       
  1865.       ReconSkippedBlock16(vid_stream->past->luminance, forw_lum,
  1866.               row, col, row_size, recon_right_for, recon_down_for,
  1867.               right_half_for, down_half_for);
  1868.       ReconSkippedBlock8(vid_stream->past->Cr, forw_cr, crow, ccol, half_row,
  1869.              c_right_for, c_down_for, c_right_half_for, c_down_half_for);
  1870.       ReconSkippedBlock8(vid_stream->past->Cb, forw_cb, crow, ccol, half_row,
  1871.              c_right_for, c_down_for, c_right_half_for, c_down_half_for);
  1872.     }
  1873.     /* If back predicted, calculate prediction values. */
  1874.     
  1875.     if (vid_stream->mblock.bpict_past_back) {
  1876.       ReconSkippedBlock16(vid_stream->future->luminance, back_lum,
  1877.               row, col, row_size, recon_right_back, recon_down_back,
  1878.               right_half_back, down_half_back);
  1879.       ReconSkippedBlock8(vid_stream->future->Cr, back_cr, crow, ccol, half_row,
  1880.              c_right_back, c_down_back,
  1881.              c_right_half_back, c_down_half_back);
  1882.       ReconSkippedBlock8(vid_stream->future->Cb, back_cb, crow, ccol, half_row,
  1883.              c_right_back, c_down_back,
  1884.              c_right_half_back, c_down_half_back);
  1885.     }
  1886.  
  1887.     h = ((short)crow * (short)half_row) + ccol;
  1888.     lum = (vid_stream->current->luminance + ((short)row * (short)row_size) + col);
  1889.  
  1890.     if (vid_stream->mblock.bpict_past_forw && !vid_stream->mblock.bpict_past_back) {
  1891.  
  1892.       PSB1_reconstruct(lum, forw_lum, row_incr);
  1893.  
  1894.       PSB2_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1895.                forw_cr, forw_cb, half_row_incr);
  1896.  
  1897.     } else if (vid_stream->mblock.bpict_past_back && !vid_stream->mblock.bpict_past_forw) {
  1898.  
  1899.       PSB1_reconstruct(lum, back_lum, row_incr);
  1900.  
  1901.       PSB2_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1902.                back_cr, back_cb, half_row_incr);
  1903.     } else {
  1904.       PSB3_reconstruct(lum, forw_lum, back_lum, row_size);
  1905.  
  1906.       PSB4_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1907.                forw_cr, back_cr, forw_cb, back_cb, half_row);
  1908.     }    
  1909.   }
  1910. }
  1911.  
  1912.  
  1913.  
  1914. /* MR
  1915.  *--------------------------------------------------------------
  1916.  *
  1917.  * ReconSkippedBlock -- width 16
  1918.  *
  1919.  *    Reconstructs predictive block for skipped macroblocks
  1920.  *      in B Frames.
  1921.  *
  1922.  * Results:
  1923.  *    No return values.
  1924.  *
  1925.  * Side effects:
  1926.  *    None.
  1927.  *
  1928.  *--------------------------------------------------------------
  1929.  */
  1930.  
  1931. static void ReconSkippedBlock16(unsigned char *source, unsigned char *dest, int row, int col, int row_size,
  1932.                     int right, int down, int right_half, int down_half)
  1933. {
  1934.   source += ((short)(row + down) * (short)row_size) + col + right;
  1935.  
  1936.   if ((!right_half) && (!down_half))
  1937.     RSB1_reconstruct(dest, source, row_size);
  1938.   else 
  1939.     RSB2_reconstruct(dest, source, source + right_half + ((short)row_size * (short)down_half), row_size);
  1940. }
  1941.  
  1942. /* MR
  1943.  *--------------------------------------------------------------
  1944.  *
  1945.  * ReconSkippedBlock -- width 8
  1946.  *
  1947.  *    Reconstructs predictive block for skipped macroblocks
  1948.  *      in B Frames.
  1949.  *
  1950.  * Results:
  1951.  *    No return values.
  1952.  *
  1953.  * Side effects:
  1954.  *    None.
  1955.  *
  1956.  *--------------------------------------------------------------
  1957.  */
  1958.  
  1959. static void ReconSkippedBlock8(unsigned char *source, unsigned char *dest, int row, int col, int row_size,
  1960.                    int right, int down, int right_half, int down_half)
  1961. {
  1962.   source += ((short)(row + down) * (short)row_size) + col + right;
  1963.  
  1964.   if ((!right_half) && (!down_half))
  1965.     RSB3_reconstruct(dest, source, row_size);
  1966.   else 
  1967.     RSB4_reconstruct(dest, source, source + right_half + ((short)row_size * (short)down_half), row_size);
  1968. }
  1969.  
  1970.  
  1971. /*
  1972.  *--------------------------------------------------------------
  1973.  *
  1974.  * DoPictureDisplay --
  1975.  *
  1976.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  1977.  *      image in lum plane. Updates past and future frame
  1978.  *      pointers. Dithers image. Sends to display mechanism.
  1979.  *
  1980.  * Results:
  1981.  *    Pict image structure locked if displaying or if frame
  1982.  *      is needed as past or future reference.
  1983.  *
  1984.  * Side effects:
  1985.  *    Lum plane pummelled.
  1986.  *
  1987.  *--------------------------------------------------------------
  1988.  */
  1989.  
  1990. static void DoPictureDisplay(VidStream *vid_stream)
  1991. {
  1992.  
  1993.   /* init display, if needed */
  1994.  
  1995.   if(!vid_stream->display_is_initialized)
  1996.   {
  1997.     ResizeDisplay(vid_stream->h_size, vid_stream->v_size);
  1998.     vid_stream->display_is_initialized = TRUE;
  1999.   }
  2000.  
  2001.   /* Convert to colormap space and dither. */
  2002.  
  2003.   DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  2004.         vid_stream->current->Cb, vid_stream->current->display,
  2005.         vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  2006.  
  2007.   /* Update past and future references if needed. */
  2008.  
  2009.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  2010.     if (vid_stream->future == NULL) {
  2011.       vid_stream->future = vid_stream->current;
  2012.       vid_stream->future->locked |= FUTURE_LOCK;
  2013.     } else {
  2014.       if (vid_stream->past != NULL) {
  2015.     vid_stream->past->locked &= ~PAST_LOCK;
  2016.       }
  2017.       vid_stream->past = vid_stream->future;
  2018.       vid_stream->past->locked &= ~FUTURE_LOCK;
  2019.       vid_stream->past->locked |= PAST_LOCK;
  2020.       vid_stream->future = vid_stream->current;
  2021.       vid_stream->future->locked |= FUTURE_LOCK;
  2022.       vid_stream->current = vid_stream->past;
  2023.       ExecuteDisplay(vid_stream);
  2024.     }
  2025.   } else
  2026.     ExecuteDisplay(vid_stream);
  2027.  
  2028. }
  2029.  
  2030.  
  2031.  
  2032. /*
  2033.  *--------------------------------------------------------------
  2034.  *
  2035.  * ToggleBFlag --
  2036.  *
  2037.  *    Called to set no b frame processing flag.
  2038.  *
  2039.  * Results:
  2040.  *      No_B_Flag flag is toggled from present value to opposite value.
  2041.  *
  2042.  * Side effects:
  2043.  *      None.
  2044.  *
  2045.  *--------------------------------------------------------------
  2046.  */
  2047.  
  2048. void ToggleBFlag(void)
  2049. {
  2050.   No_B_Flag ^= 0xffff;
  2051. }
  2052.  
  2053.  
  2054.  
  2055.  
  2056. /*
  2057.  *--------------------------------------------------------------
  2058.  *
  2059.  * TogglePFlag --
  2060.  *
  2061.  *    Called to set no p frame processing flag.
  2062.  *
  2063.  * Results:
  2064.  *      No_P_Flag flag is toggled from present value to opposite value.
  2065.  *
  2066.  * Side effects:
  2067.  *      None.
  2068.  *
  2069.  *--------------------------------------------------------------
  2070.  */
  2071.  
  2072. void TogglePFlag(void)
  2073. {
  2074.   No_P_Flag ^= 0xffff;
  2075. }
  2076.